package fr.inria.phoenix.scenario.bwsnfirefighting.framework.distributed.alertdetection;

import java.util.HashMap;

import fr.inria.diagen.core.ServiceConfiguration;
import fr.inria.diagen.core.exception.DiaGenException;
import fr.inria.diagen.core.exception.InvocationException;
import fr.inria.diagen.core.network.RemoteServiceInfo;
import fr.inria.diagen.core.service.local.Service;

import fr.inria.phoenix.scenario.bwsnfirefighting.framework.datatype.DangerLevel;
import java.lang.Boolean;
import fr.inria.phoenix.scenario.bwsnfirefighting.framework.datatype.Location;

import fr.inria.phoenix.scenario.bwsnfirefighting.framework.datatype.SmokeDetectionDataType;
import fr.inria.phoenix.scenario.bwsnfirefighting.framework.datatype.SmokeDetectionIndices;import fr.inria.phoenix.scenario.bwsnfirefighting.framework.datatype.TemperatureDetectionDataType;
import fr.inria.phoenix.scenario.bwsnfirefighting.framework.datatype.TemperatureDetectionIndices;
import fr.inria.phoenix.scenario.bwsnfirefighting.framework.datatype.AlertDetectionDataType;
import fr.inria.phoenix.scenario.bwsnfirefighting.framework.datatype.AlertDetectionIndices;
import fr.inria.diagen.core.service.proxy.Proxy;
import fr.inria.diagen.core.module.event.IEventNotifyListener;
import fr.inria.diagen.core.module.command.ICommandListener;
import fr.inria.diagen.core.server.local.EventSubscription;
import fr.inria.diagen.core.service.filter.service.ServiceFilter;
import fr.inria.diagen.core.exception.InvocationException;

/**
 * Set a level Danger by inspecting the overall situation of the sensing data
 *
 * @[79,0]
 * context AlertDetection as DangerLevel indexed by location as Location {
 * source activated from ManualButton;
 * context SmokeDetection;
 * context TemperatureDetection;
 * }
 */
public abstract class AlertDetection extends Service implements IEventNotifyListener, ICommandListener {
  /**
     * @param serviceConfiguration
     */
    public AlertDetection(ServiceConfiguration serviceConfiguration ) {
      super("AlertDetection", serviceConfiguration, GeneratedFramework.getInstance());
    }

	protected final void _postInitialize() {
			subscribeTemperatureDetection();
				subscribeSmokeDetection();
		
		postInitialize();
	}
	protected void postInitialize() {}


    private HashMap<AlertDetectionIndices,fr.inria.phoenix.scenario.bwsnfirefighting.framework.datatype.DangerLevel> alertDetection = new HashMap<AlertDetectionIndices,fr.inria.phoenix.scenario.bwsnfirefighting.framework.datatype.DangerLevel>();
    /**
     * @[79,0]
     * context AlertDetection as DangerLevel indexed by location as Location {
     * source activated from ManualButton;
     * context SmokeDetection;
     * context TemperatureDetection;
     * }
     */  
    protected void setAlertDetection(fr.inria.phoenix.scenario.bwsnfirefighting.framework.datatype.DangerLevel newAlertDetectionValue , fr.inria.phoenix.scenario.bwsnfirefighting.framework.datatype.Location location) {
      AlertDetectionIndices _indices_ = new AlertDetectionIndices(location);
      alertDetection.put(_indices_,newAlertDetectionValue);
      getServer().publish("AlertDetection", new AlertDetectionDataType(newAlertDetectionValue, location)); 
    }

    /**
     * @[79,0]
     * context AlertDetection as DangerLevel indexed by location as Location {
     * source activated from ManualButton;
     * context SmokeDetection;
     * context TemperatureDetection;
     * }
     */
    protected fr.inria.phoenix.scenario.bwsnfirefighting.framework.datatype.DangerLevel getAlertDetection(fr.inria.phoenix.scenario.bwsnfirefighting.framework.datatype.Location location) {
      return alertDetection.get(new AlertDetectionIndices(location));    }
    
    public final Object commandReceived(RemoteServiceInfo rsi, String methodName, Object... args) throws DiaGenException {
      if (methodName.equals("getAlertDetection"))
        return (fr.inria.phoenix.scenario.bwsnfirefighting.framework.datatype.DangerLevel) getAlertDetection((fr.inria.phoenix.scenario.bwsnfirefighting.framework.datatype.Location)args[0]);

      throw new InvocationException("Unsupported method call: " + methodName);
    }
    
    public void notifyReceived(RemoteServiceInfo servicePublisher, String eventName, Object arg) {
        try {
          if (eventName.equals("SmokeDetection") && servicePublisher.getClassName().equals("SmokeDetection")) {
            SmokeDetectionDataType data = (SmokeDetectionDataType) arg;
            onNewSmokeDetection ((java.lang.Boolean) data._dataSourceValue_, data.indices.location);          }
 else          if (eventName.equals("activated") && servicePublisher.getClassName().equals("ManualButton")) {
            onNewActivated ((ManualButtonProxy) createProxy(servicePublisher),(java.lang.Boolean) arg);          }
 else          if (eventName.equals("TemperatureDetection") && servicePublisher.getClassName().equals("TemperatureDetection")) {
            TemperatureDetectionDataType data = (TemperatureDetectionDataType) arg;
            onNewTemperatureDetection ((fr.inria.phoenix.scenario.bwsnfirefighting.framework.datatype.DangerLevel) data._dataSourceValue_, data.indices.location);          }

        } catch (Exception e) {
              e.printStackTrace();
        }
    }

    public abstract void onNewSmokeDetection(java.lang.Boolean newSmokeDetectionValue, fr.inria.phoenix.scenario.bwsnfirefighting.framework.datatype.Location location);
    
    
    private final void subscribeSmokeDetection() {
      getServer().subscribe(new EventSubscription(getSmokeDetectionRSI(), getServiceInfo(), "SmokeDetection"), 3600);
    }

    private RemoteServiceInfo getSmokeDetectionRSI() {
      ServiceFilter filter = new ServiceFilter("SmokeDetection");
      RemoteServiceInfo[] rsis = getServicesInfo(getServer(), filter);
      return rsis[0];
    }
    
    protected final java.lang.Boolean getSmokeDetection(fr.inria.phoenix.scenario.bwsnfirefighting.framework.datatype.Location location) throws InvocationException {
      return (java.lang.Boolean) getProcessor().command(getSmokeDetectionRSI(), "getSmokeDetection", location);
    }    public abstract void onNewActivated(ManualButtonProxy proxy,java.lang.Boolean newActivatedValue);
    
    public void subscribeActivated(ManualButtonProxy proxy) {
      getServer().subscribe(new EventSubscription(proxy.getRemoteServiceInfo(), getServiceInfo(), "activated"), 3600);
    }    public abstract void onNewTemperatureDetection(fr.inria.phoenix.scenario.bwsnfirefighting.framework.datatype.DangerLevel newTemperatureDetectionValue, fr.inria.phoenix.scenario.bwsnfirefighting.framework.datatype.Location location);
    
    
    private final void subscribeTemperatureDetection() {
      getServer().subscribe(new EventSubscription(getTemperatureDetectionRSI(), getServiceInfo(), "TemperatureDetection"), 3600);
    }

    private RemoteServiceInfo getTemperatureDetectionRSI() {
      ServiceFilter filter = new ServiceFilter("TemperatureDetection");
      RemoteServiceInfo[] rsis = getServicesInfo(getServer(), filter);
      return rsis[0];
    }
    
    protected final fr.inria.phoenix.scenario.bwsnfirefighting.framework.datatype.DangerLevel getTemperatureDetection(fr.inria.phoenix.scenario.bwsnfirefighting.framework.datatype.Location location) throws InvocationException {
      return (fr.inria.phoenix.scenario.bwsnfirefighting.framework.datatype.DangerLevel) getProcessor().command(getTemperatureDetectionRSI(), "getTemperatureDetection", location);
    }
    

    protected final ManualButtonComposite discover(ManualButtonServiceFilter filter) {
      RemoteServiceInfo[] rsis = getServicesInfo(getServer(), filter);
      ManualButtonProxy[] proxies = new ManualButtonProxy[rsis.length];
      for (int i = 0; i < rsis.length; i++) {
        proxies[i] = new ManualButtonProxy(getProcessor(), rsis[i]);
      }
      return new ManualButtonComposite(proxies, this);
    }
    
    protected final ManualButtonComposite allManualButtons() {
        return discover(new ManualButtonServiceFilter());
    }
    
    protected final ManualButtonServiceFilter manualButtonsWhere() {
        return new ManualButtonServiceFilter();
    }

}